﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace IOT_Config
{
    enum SerialDataWidth
    {
        DataWidth_5B,
        DataWidth_6B,
        DataWidth_7B,
        DataWidth_8B,
        DataWidth_9B,
    };

    enum SerialParity
    {
        None,
        Odd,
        Even,
        Mark,
        Space,
    }

    enum SerialStopBits
    {
        StopBits_0_5,
        StopBits_1,
        StopBits_1_5,
        StopBits_2,
    }

    class IOTSerial
    {
        public int baudrate { get; set; }
        public SerialDataWidth dataWidth { get; set; }
        public SerialParity parity { get; set; }
        public SerialStopBits stopBits { get; set; }
    }

    enum ModuleMode
    {
        UDP_Client = 0,
        TCP_Client = 1,
        UDP_Server = 2,
        TCP_Server = 3,
    }

    enum IPMode
    {
        DHCP = 0,
        STATIC = 1,
    }

    enum InfoOffset
    {
        MACAddr = 0,
        WorkMode = 6,
        IPMode = 7,
        LocalIP = 8,
        Netmask = 12,
        Gateway = 16,
        DNS = 20,
        LocalPort = 24,
        RemoteIP1 = 26,
        RemotePort1 = 30,
        SerialCfg = 32,
        ModuleID = 40,
        HttpAuthKey = 48
    }

    class IOTDevice
    {
        public byte[] macAddr { get; set; }
        public ModuleMode moduleMode { get; set; }
        public IPMode ipMode { get; set; }
        public IPAddress localIP { get; set; }
        public IPAddress netmask { get; set; }
        public IPAddress gateway { get; set; }
        public IPAddress dnsServer { get; set; }

        public ushort localPort { get; set; }
        public IPAddress remoteIP { get; set; }
        public ushort remotePort { get; set; }

        public IOTSerial iotSerial { get; set; }

        public long moduleID { get; set; }

        public EndPoint configEndPoint { get; set; }

        public IOTDevice()
        {
            macAddr = new byte[6];
            iotSerial = new IOTSerial();
        }

        public byte[] toByteArray()
        {
            byte[] buffer = new byte[64];
            byte[] ptr = buffer;
            int offset = 0;

            /* MAC Address */
            offset = (int)InfoOffset.MACAddr;
            Array.Copy(macAddr, 0, buffer, offset, 6);


            /* module work mode */
            offset = (int)InfoOffset.WorkMode;
            buffer[offset] = (byte)moduleMode;

            /* IP address mode */
            offset = (int)InfoOffset.IPMode;
            buffer[offset] = (byte)ipMode;

            /* module IP address */
            offset = (int)InfoOffset.LocalIP;
            Array.Copy(localIP.GetAddressBytes(), 0, buffer, offset, 4);

            /* module netmask */
            offset = (int)InfoOffset.Netmask;
            Array.Copy(netmask.GetAddressBytes(), 0, buffer, offset, 4);

            /* module gateway */
            offset = (int)InfoOffset.Gateway;
            Array.Copy(gateway.GetAddressBytes(), 0, buffer, offset, 4);

            /* module DNS server address */
            offset = (int)InfoOffset.DNS;
            Array.Copy(dnsServer.GetAddressBytes(), 0, buffer, offset, 4);

            /* module local port */
            offset = (int)InfoOffset.LocalPort;
            byte[] localPortArr = BitConverter.GetBytes(localPort);
            Array.Copy(localPortArr, 0, buffer, offset, 2);

            /* remote IP1 address */
            offset = (int)InfoOffset.RemoteIP1;
            Array.Copy(remoteIP.GetAddressBytes(), 0, buffer, offset, 4);

            /* remote IP1 port */
            offset = (int)InfoOffset.RemotePort1;
            byte[] remotePortArr = BitConverter.GetBytes(remotePort);
            Array.Copy(remotePortArr, 0, buffer, offset, 2);

            /* serial baud rate */
            offset = (int)InfoOffset.SerialCfg;
            byte[] baudRateArr = BitConverter.GetBytes(iotSerial.baudrate);
            Array.Copy(baudRateArr, 0, buffer, offset, 4);
            buffer[offset + 4] = (byte)iotSerial.dataWidth;
            buffer[offset + 5] = (byte)iotSerial.parity;
            buffer[offset + 6] = (byte)iotSerial.stopBits;

            /* 计算校验和 */
            int i, sum = 0;
            for (i = 0; i < 63; i++)
                sum += buffer[i];
            buffer[63] = (byte)(sum & 0xFF);

            return buffer;
        }

        public static IOTDevice Parse(byte[] buffer)
        {
            IOTDevice device = new IOTDevice();
            int offset = 0;

            /* MAC address */
            Array.Copy(buffer, device.macAddr, 6);

            /* module work mode */
            offset = (int)InfoOffset.WorkMode;
            device.moduleMode = (ModuleMode)Enum.ToObject(typeof(ModuleMode), buffer[offset]);

            /* IP address mode */
            offset = (int)InfoOffset.IPMode;
            device.ipMode = (IPMode)Enum.ToObject(typeof(IPMode), buffer[offset]);

            /* module IP address */
            byte[] mip = new byte[4];
            offset = (int)InfoOffset.LocalIP;
            Array.Copy(buffer, offset, mip, 0, 4);
            device.localIP = new IPAddress(mip);

            /* module netmask */
            byte[] nmask = new byte[4];
            offset = (int)InfoOffset.Netmask;
            Array.Copy(buffer, offset, nmask, 0, 4);
            device.netmask = new IPAddress(nmask);

            /* module gateway */
            byte[] gatewayArr = new byte[4];
            offset = (int)InfoOffset.Gateway;
            Array.Copy(buffer, offset, gatewayArr, 0, 4);
            device.gateway = new IPAddress(gatewayArr);

            /* module DNS server address */
            byte[] dnsServerArr = new byte[4];
            offset = (int)InfoOffset.DNS;
            Array.Copy(buffer, offset, dnsServerArr, 0, 4);
            device.dnsServer = new IPAddress(dnsServerArr);

            /* module local port */
            offset = (int)InfoOffset.LocalPort;
            ushort modulePort = BitConverter.ToUInt16(buffer, offset);
            device.localPort = modulePort;

            /* remote IP1 address */
            byte[] rip = new byte[4];
            offset = (int)InfoOffset.RemoteIP1;
            Array.Copy(buffer, offset, rip, 0, 4);
            device.remoteIP = new IPAddress(rip);

            /* remote IP1 port */
            offset = (int)InfoOffset.RemotePort1;
            ushort remotePort = BitConverter.ToUInt16(buffer, offset);
            device.remotePort = remotePort;

            /* serial baud rate */
            offset = (int)InfoOffset.SerialCfg;
            int baudRate = BitConverter.ToInt32(buffer, offset);
            device.iotSerial.baudrate = baudRate;
            device.iotSerial.dataWidth = (SerialDataWidth)Enum.ToObject(typeof(SerialDataWidth), buffer[offset + 4]);
            device.iotSerial.parity = (SerialParity)Enum.ToObject(typeof(SerialParity), buffer[offset + 5]);
            device.iotSerial.stopBits = (SerialStopBits)Enum.ToObject(typeof(SerialStopBits), buffer[offset + 6]);

            /* module ID */
            offset = (int)InfoOffset.ModuleID;
            device.moduleID = BitConverter.ToInt64(buffer, offset);

            return device;
        }
    }
}
